/*
 * pent_low.cpp
 *
 *  Created on: Jul 1, 2011
 *      Author: denis
 */
#include "pent_low.h"
#include "init_pent.h"
#define X_MIN 0
#define Y_MIN 0
#define X_MAX 10
#define Y_MAX 6
#define ALLOWED_BITS     0x0FFFFFFFFFFFFFFFLLU
#define LEFT_NULL_COLUMN  0x7FDFF7FDFF7FDFFLLU
#define RIGHT_NULL_COLUMN 0xFFBFEFFBFEFFBFELLU
#define TOP_NULL_ROW     0x003FFFFFFFFFFFFLLU
#define BOTTOM_NULL_ROW  0xFFFFFFFFFFFFC00LLU

Pentamino_Low::Pentamino_Low(longvector* previous_steps_array,	pentaminos_vector* pentaminos_array, std::ofstream* in_destfile) {
		longvector::iterator itt;
		destfile=in_destfile;
		iprevious_steps_array= new longvector;
		for(itt=previous_steps_array->begin();itt!=previous_steps_array->end();itt++){
			iprevious_steps_array->push_back(*itt);
		}
		ipentaminos_vector = pentaminos_array;
	}

	void Pentamino_Low::trim_to_depth(int tdepth){
		longvector* new_array= new longvector;
		for(int count=0;count<tdepth;count++){
					new_array->push_back((*iprevious_steps_array)[count]);
		}
		delete(iprevious_steps_array);
		iprevious_steps_array=new_array;
	}

	unsigned long long Pentamino_Low::cur_fil_upd(){
		longvector::iterator it;
		current_field_status=0;
		for (it = iprevious_steps_array->begin(); it!= iprevious_steps_array->end(); it++){ // making map of all currently laid pentaminos
			current_field_status = current_field_status ^ (*it);
		}
		return current_field_status;
	}

	bool Pentamino_Low::CheckRegions(unsigned long long m_field){
		unsigned long long field =~m_field & ALLOWED_BITS;
		unsigned long long ft=field;
		unsigned long long area,area_prev,cp_area;
		unsigned long long first_one=0;
		int region_size=0;
		bool flag=true;

		while ((field != 0)and flag){
			ft=field;
			ft= ft& (ft-1);
			first_one=(field) ^ ft;
			area=first_one;
			area_prev=area+1;
			while (area_prev!=area)	{
				area_prev=area;
				area=area|((area_prev>>1) & LEFT_NULL_COLUMN );
				area=area|((area_prev<<1) & RIGHT_NULL_COLUMN);
				area=area|((area_prev>>10)&TOP_NULL_ROW);
				area=area|((area_prev<<10) & BOTTOM_NULL_ROW);
				area = field & area;
			}
			cp_area=area;
			field=field -area;
			region_size=0;
			while (cp_area !=0){
				cp_area=cp_area&(cp_area-1);
				region_size++;

			}
			flag= (region_size % 5) ==0;
		}
	return flag;
	}

	int Pentamino_Low::subs(unsigned long long figure,int step,unsigned long long filter,unsigned long long boundary){
		int isubs=-1;//because we must count initial position too
		while(((~filter)&figure)!=0){
			figure=(figure<<step)&boundary;
			isubs++;
			}
		return isubs;
	};
	int Pentamino_Low::ysubs(unsigned long long figure){
		return subs(figure,X_MAX,TOP_NULL_ROW,BOTTOM_NULL_ROW);
	}
	int Pentamino_Low::xsubs(unsigned long long figure){
		return subs(figure,1,LEFT_NULL_COLUMN,RIGHT_NULL_COLUMN);

    }

	void Pentamino_Low::printsolution(){
		for (element = iprevious_steps_array->begin(); element!= iprevious_steps_array->end(); element++) {

			std::cout<< *element<<' ';
			*destfile<< *element<<' ';
			}
			//current_field_status=0;
			//std::cout << "\n";
			for (element = iprevious_steps_array->begin(); element!= iprevious_steps_array->end(); element++) {
										//print_int(*element);
										//current_field_status=current_field_status ^ *element;
										//m_print_int(current_field_status);
			}
			//iprevious_steps_array->clear();
			*destfile<<"\n";
			std::cout << "\n";

	};
	longvector* Pentamino_Low::rot_depth(int f_depth){
		return (*ipentaminos_vector)[f_depth];

	}
	bool Pentamino_Low::isSameFigure(unsigned long long template_figure,unsigned long long init_figure){
		//Checking if figure is translated template_figure
		unsigned long long figure=init_figure;
		while(((~LEFT_NULL_COLUMN)&figure)==0){
					figure=(figure<<1);
		}
		while(((~TOP_NULL_ROW)&figure)==0){
							figure=(figure<<X_MAX);
		}
		return (figure==template_figure);
	}
	bool Pentamino_Low::Check11(unsigned long long field){
		longvector* elev_rotations=(*ipentaminos_vector)[11];
		unsigned long long elev_default_current_position;
		unsigned long long figure;
		bool result=0;
		figure=(~field)&ALLOWED_BITS;
		while(((~LEFT_NULL_COLUMN)&figure)==0){
							figure=(figure<<1);
				}
		while(((~TOP_NULL_ROW)&figure)==0){
			figure=(figure<<X_MAX);
		}
		//print_int(field);
		//std::cout<<CheckRegions(field)<<','<<field<<"\n";
		for( int ecount=0;ecount<elev_rotations->size();ecount++){
			elev_default_current_position=(*elev_rotations)[ecount];

			result=result||(figure==elev_default_current_position);
			}
		return result;
	}



